<template>
    <div class="editor-container">
        <Toolbar class="editor-toolbar" :editor="editorRef" :mode="mode" />
        <Editor class="editor-area"
            :style="{height}"
            v-model="state.editorVal"
            :defaultConfig="state.editorConfig"
            :mode="mode"
            @onCreated="handleCreated"
            @onChange="handleChange"
        />
    </div>
</template>

<script setup lang="ts" name="WangEditor">
import '@wangeditor/editor/dist/css/style.css'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef, watch } from 'vue'
import type { IDomEditor } from '@wangeditor/editor';
import { uploadImg } from '@/api/common/media'

interface Props {
    mode?: 'default' | 'simple'; // 模式，默认 default
    disable?: boolean; // 是否禁用
    placeholder?: string; // 内容框提示信息
    height?: string; // 内容框高度
    text?: string; // 双向绑定，用于获取 editor.getText()
    modeValue: string; // 双向绑定，用于获取 editor.getHtml()
}

// 定义父组件传过来的prop
const props = withDefaults(defineProps<Props>(), {
    mode: 'default',
    disable: false,
    placeholder: '请输入内容',
    height: '300px',
    text: '',
    modeValue: '',
})

// 定义事件
const emit = defineEmits(['update:text', 'update:modeValue'])

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()
const state = reactive({
    editorVal: props.modeValue,
    editorConfig: {
        placeholder: props.placeholder,
        MENU_CONF: {} as any
    }
})

// 上传文件配置
state.editorConfig.MENU_CONF['uploadImage'] = {
    async customUpload(file: File, insertFn: Function) {
        const form = new FormData()
        form.append('file', file)
        // 其他数据转成json字符串传递给后台
        form.append('data', JSON.stringify({ sourceType: 'goods_img' }))
        // 开始上传
        const { data } = await uploadImg(form)
        // 上传成功
        insertFn(data)
    }
}

// 编辑器回调函数
const handleCreated = (editor: IDomEditor) => {
    editorRef.value = editor
}

// 编辑器内容改变时
const handleChange = (editor: IDomEditor) => {
    emit('update:modeValue', editor.getHtml())
    emit('update:text', editor.getText())
}

// 监听双向绑定值改变，用于回显
watch(() => props.modeValue, (newVal) => {
    state.editorVal = newVal
})

// 监听是否禁用改变
watch(() => props.disable, (newVal) => {
    nextTick(() => {
        const editor = editorRef.value
        if (editor == null) return
        newVal ? editor.disable() : editor.enable()
    })
}, { immediate: true })

// 组件销毁时，销毁编辑器实例
onBeforeUnmount(() => {
    const editor = editorRef.value
    if (editor == null) return
    editor.destroy()
})
</script>

<style lang="scss" scoped>
.ediotr-container {
    .editor-toolbar {
        border-radius: 3px 3px 0 0;
        border: 1px solid var(--el-border-color-light) !important;
    }
    .editor-area {
        border: 1px solid var(--el-border-color-light) !important;
        border-radius: 0 0 3px 3px;
    }
}
</style>